"""
任务调度器模块

负责管理和调度多个备份任务的执行。
"""

import os
import logging
import threading
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Dict, Any, Callable, Optional
from datetime import datetime


class TaskScheduler:
    """任务调度器
    
    负责调度和管理多个备份任务的并行执行。
    """
    
    def __init__(self, max_workers: int = 3):
        """初始化任务调度器
        
        参数:
            max_workers (int): 最大并行工作线程数
                示例值: 3
        """
        self.max_workers = max_workers
        self.logger = self._setup_logging()
        self.results = {}
        self._stop_event = threading.Event()
        self._running = False
    
    def _setup_logging(self) -> logging.Logger:
        """设置日志记录器
        
        返回:
            logging.Logger: 配置好的日志记录器
        """
        logger = logging.getLogger("database_backup.task_scheduler")
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger
    
    def schedule_tasks(self, tasks: List[Dict[str, Any]], 
                      task_function: Callable[[Dict[str, Any]], Dict[str, Any]]) -> Dict[str, Any]:
        """调度任务执行
        
        参数:
            tasks (List[Dict[str, Any]]): 任务配置列表
            task_function (Callable): 任务执行函数
        
        返回:
            Dict[str, Any]: 调度结果汇总
        """
        self.logger.info(f"开始调度 {len(tasks)} 个备份任务，最大并行数: {self.max_workers}")
        
        start_time = time.time()
        results = {}
        
        # 使用线程池执行任务
        with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            # 提交所有任务
            future_to_task = {}
            for task in tasks:
                task_name = task['_config_name']
                future = executor.submit(task_function, task)
                future_to_task[future] = task_name
            
            # 收集结果
            completed_count = 0
            for future in as_completed(future_to_task):
                task_name = future_to_task[future]
                try:
                    result = future.result()
                    results[task_name] = result
                    completed_count += 1
                    
                    if result.get('success', False):
                        self.logger.info(f"任务 {task_name} 完成: {result.get('message', '成功')}")
                    else:
                        self.logger.error(f"任务 {task_name} 失败: {result.get('error', '未知错误')}")
                        
                except Exception as e:
                    results[task_name] = {
                        'success': False,
                        'error': str(e),
                        'task_name': task_name
                    }
                    self.logger.error(f"任务 {task_name} 执行异常: {e}")
                
                # 显示进度
                progress = (completed_count / len(tasks)) * 100
                self.logger.info(f"进度: {completed_count}/{len(tasks)} ({progress:.1f}%)")
        
        end_time = time.time()
        execution_time = end_time - start_time
        
        # 汇总结果
        summary = self._generate_summary(results, execution_time)
        self._log_summary(summary)
        
        return summary
    
    def _generate_summary(self, results: Dict[str, Any], execution_time: float) -> Dict[str, Any]:
        """生成执行结果汇总
        
        参数:
            results (Dict[str, Any]): 任务执行结果
            execution_time (float): 总执行时间
        
        返回:
            Dict[str, Any]: 汇总信息
        """
        total_tasks = len(results)
        successful_tasks = sum(1 for result in results.values() if result.get('success', False))
        failed_tasks = total_tasks - successful_tasks
        
        summary = {
            'total_tasks': total_tasks,
            'successful_tasks': successful_tasks,
            'failed_tasks': failed_tasks,
            'success_rate': (successful_tasks / total_tasks * 100) if total_tasks > 0 else 0,
            'execution_time': execution_time,
            'start_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            'results': results
        }
        
        # 统计备份文件信息
        total_files = 0
        total_size = 0
        
        for result in results.values():
            if result.get('success', False):
                backup_files = result.get('backup_files', [])
                total_files += len(backup_files)
                
                # 计算文件大小
                for file_path in backup_files:
                    if os.path.exists(file_path):
                        total_size += os.path.getsize(file_path)
        
        summary['total_backup_files'] = total_files
        summary['total_backup_size'] = self._format_file_size(total_size)
        
        return summary
    
    def _format_file_size(self, size_bytes: int) -> str:
        """格式化文件大小
        
        参数:
            size_bytes (int): 文件大小（字节）
        
        返回:
            str: 格式化后的文件大小
        """
        if size_bytes == 0:
            return "0B"
        
        size_names = ["B", "KB", "MB", "GB"]
        i = 0
        while size_bytes >= 1024 and i < len(size_names) - 1:
            size_bytes /= 1024.0
            i += 1
        
        return f"{size_bytes:.2f}{size_names[i]}"
    
    def _log_summary(self, summary: Dict[str, Any]):
        """记录汇总信息
        
        参数:
            summary (Dict[str, Any]): 汇总信息
        """
        self.logger.info("=" * 60)
        self.logger.info("备份任务执行汇总")
        self.logger.info("=" * 60)
        self.logger.info(f"总任务数: {summary['total_tasks']}")
        self.logger.info(f"成功任务: {summary['successful_tasks']}")
        self.logger.info(f"失败任务: {summary['failed_tasks']}")
        self.logger.info(f"成功率: {summary['success_rate']:.1f}%")
        self.logger.info(f"总执行时间: {summary['execution_time']:.2f}秒")
        self.logger.info(f"总备份文件数: {summary['total_backup_files']}")
        self.logger.info(f"总备份大小: {summary['total_backup_size']}")
        self.logger.info(f"开始时间: {summary['start_time']}")
        self.logger.info("=" * 60)
        
        # 记录失败任务的详细信息
        if summary['failed_tasks'] > 0:
            self.logger.warning("失败任务详情:")
            for task_name, result in summary['results'].items():
                if not result.get('success', False):
                    self.logger.warning(f"  - {task_name}: {result.get('error', '未知错误')}")
    
    def schedule_sequential(self, tasks: List[Dict[str, Any]], 
                          task_function: Callable[[Dict[str, Any]], Dict[str, Any]]) -> Dict[str, Any]:
        """顺序执行任务（用于调试或单线程执行）
        
        参数:
            tasks (List[Dict[str, Any]]): 任务配置列表
            task_function (Callable): 任务执行函数
        
        返回:
            Dict[str, Any]: 执行结果汇总
        """
        self.logger.info(f"开始顺序执行 {len(tasks)} 个备份任务")
        
        start_time = time.time()
        results = {}
        
        for i, task in enumerate(tasks, 1):
            task_name = task['_config_name']
            self.logger.info(f"执行任务 {i}/{len(tasks)}: {task_name}")
            
            try:
                result = task_function(task)
                results[task_name] = result
                
                if result.get('success', False):
                    self.logger.info(f"任务 {task_name} 完成: {result.get('message', '成功')}")
                else:
                    self.logger.error(f"任务 {task_name} 失败: {result.get('error', '未知错误')}")
                    
            except Exception as e:
                results[task_name] = {
                    'success': False,
                    'error': str(e),
                    'task_name': task_name
                }
                self.logger.error(f"任务 {task_name} 执行异常: {e}")
            
            # 显示进度
            progress = (i / len(tasks)) * 100
            self.logger.info(f"进度: {i}/{len(tasks)} ({progress:.1f}%)")
        
        end_time = time.time()
        execution_time = end_time - start_time
        
        # 汇总结果
        summary = self._generate_summary(results, execution_time)
        self._log_summary(summary)
        
        return summary
    
    def schedule_loop(self, 
                     get_tasks_func: Callable[[], List[Dict[str, Any]]],
                     task_function: Callable[[Dict[str, Any]], Dict[str, Any]],
                     interval_seconds: int = 3600,
                     max_iterations: Optional[int] = None) -> None:
        """循环调度任务执行
        
        参数:
            get_tasks_func (Callable): 获取任务列表的函数，每次循环都会调用
            task_function (Callable): 任务执行函数
            interval_seconds (int): 循环间隔时间（秒），默认1小时
            max_iterations (Optional[int]): 最大循环次数，None表示无限循环
        """
        self._stop_event.clear()
        self._running = True
        iteration = 0
        
        self.logger.info(f"开始循环调度任务，间隔: {interval_seconds}秒")
        if max_iterations:
            self.logger.info(f"最大循环次数: {max_iterations}")
        else:
            self.logger.info("无限循环模式（按Ctrl+C停止）")
        
        try:
            while not self._stop_event.is_set():
                iteration += 1
                
                # 检查是否达到最大循环次数
                if max_iterations and iteration > max_iterations:
                    self.logger.info(f"已达到最大循环次数 {max_iterations}，停止循环")
                    break
                
                self.logger.info(f"=== 第 {iteration} 次循环开始 ===")
                
                # 获取当前任务列表
                try:
                    tasks = get_tasks_func()
                    if not tasks:
                        self.logger.warning("未找到任何任务，跳过本次循环")
                    else:
                        self.logger.info(f"找到 {len(tasks)} 个任务")
                        
                        # 执行任务
                        summary = self.schedule_tasks(tasks, task_function)
                        
                        # 记录循环结果
                        self.logger.info(f"第 {iteration} 次循环完成: "
                                       f"成功 {summary['successful_tasks']}/{summary['total_tasks']} 个任务")
                        
                except Exception as e:
                    self.logger.error(f"获取或执行任务时发生错误: {e}")
                
                # 检查是否应该继续循环
                if self._stop_event.is_set():
                    self.logger.info("收到停止信号，退出循环")
                    break
                
                # 等待下一次循环
                if interval_seconds > 0:
                    self.logger.info(f"等待 {interval_seconds} 秒后进行下一次循环...")
                    
                    # 使用可中断的等待
                    wait_start = time.time()
                    while (time.time() - wait_start) < interval_seconds:
                        if self._stop_event.is_set():
                            self.logger.info("收到停止信号，提前结束等待")
                            break
                        time.sleep(1)  # 每秒检查一次停止信号
                else:
                    self.logger.info("间隔时间为0，立即进行下一次循环")
                    time.sleep(1)  # 避免CPU占用过高
                
        except KeyboardInterrupt:
            self.logger.info("收到键盘中断信号，停止循环")
        finally:
            self._running = False
            self.logger.info("循环调度已停止")
    
    def stop_loop(self):
        """停止循环调度"""
        if self._running:
            self.logger.info("正在停止循环调度...")
            self._stop_event.set()
        else:
            self.logger.info("循环调度未在运行")
    
    def is_running(self) -> bool:
        """检查循环调度是否正在运行
        
        返回:
            bool: 是否正在运行
        """
        return self._running